package com.arraylist.p3.singlelist;

/**
 * 模拟单链表
 */
public class SingleLinkedList {

     //首节点
     private Node headNode;
     //尾节点
     private Node lastNode;
     //节点数
     private int size;


     public int size(){
         return this.size;
     }

    //节点类
    private static class Node{

        //保存节点中的数据
        private Object data;
        //保存指向下一个节点的值
        private Node next;

        public Node(Object data){

            this.data=data;
        }
    }

    /**
     * 添加节点
     * @param element
     */
    public void add(Object element){

        //需要添加的元素封装成节点对象
        Node node=new Node(element);
        //链表为空
        if(headNode==null){
            headNode=node;
            lastNode=node;
        }
        else{
            lastNode.next=node;
            lastNode=node;
        }
        //更新节点值
        size++;
    }

    /**
     * 根据序号删除元素
     * @param index
     */
    public void remove(int index){

       if(index<0||index>size){
           throw new IndexOutOfBoundsException("序号不合法"+index);
       }

       //删除节点在开头
        if(index==0){
          //删除节点的下一个元素
          Node nextNode=headNode.next;
          headNode.next=null;
          //nextNode为单链表的首节点
          headNode=nextNode;
        }

        //删除节点在尾节点
        else if(index==size-1){
           //获得删除节点的前一个元素
           Node preNode=node(index-1);

           preNode.next=null;

           lastNode=preNode;
        }
        //删除阶节点在中间
        else{

            //获得index-1所对应的节点对象
            Node preNode=node(index-1);
            //获得index+1所对应的节点对象
            Node nextNode=preNode.next.next;
            //设置删除节点的值为null
            preNode.next=null;
            //设置preNode的next值为nextNode
            preNode.next=nextNode;
        }
        size--;
    }

    /**
     * 根据序号插入元素
     * @param index
     * @param element
     */
    public void add(int index,Object element){

        //判断序号是否合法
        if(index<0||index>size){
            throw  new IndexOutOfBoundsException("序号不合法"+index);
        }
        //把需要添加的数据封装成节点对象
        Node node = new Node(element);

        //插入节点在首节点
        if(index==0){
           node.next=headNode;
           headNode=node;
        }
        //插入节点在末尾的情况
        else  if(index==size){
            lastNode.next=node;
            lastNode=node;
        }
        //插入节点在中间
        else{

            Node preNode = node(index - 1);
            //获得index所对应的节点对象
            Node curNode=preNode.next;
            //设置preNode的next值为node
            preNode.next=node;
            //设置node的next值为curNode
            node.next=curNode;
        }
        size++;
    }

    /**
     * 根据序号获取元素
     * @param index
     * @return
     */
    public Object get(int index){

        //判断序号是否合法
        if(index<0||index>size){
            throw  new IndexOutOfBoundsException("序号不合法"+index);
        }
        //根据序号获得对应的节点对象
        Node node = node(index);

        return node.data;
    }


    /**
     * 根据序号获得节点对象
     * @param index
     * @return
     */
    private Node node(int index){

        Node tempNode=headNode;

        for(int i=0;i<index;i++){

            tempNode=tempNode.next;
        }
      return tempNode;
    }
}
